package com.chenxin.wms.process.outbound.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.chenxin.common.constant.WmsConstants;
import com.chenxin.common.core.domain.ProcResult;
import com.chenxin.common.enums.WmsBusinessStatus;
import com.chenxin.common.enums.WmsTaskSubType;
import com.chenxin.common.enums.WmsTaskType;
import com.chenxin.common.utils.StringUtils;
import com.chenxin.wms.domain.*;
import com.chenxin.wms.domain.po.UsableStockInfo;
import com.chenxin.wms.mapper.ObDetailMapper;
import com.chenxin.wms.mapper.ObMasterMapper;
import com.chenxin.wms.mapper.StockMapper;
import com.chenxin.wms.process.outbound.IOutboundProcess;
import com.chenxin.wms.process.task.ITaskProcess;
import com.chenxin.wms.service.IModuleSerialService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

@Service
public class OutboundProcessImpl implements IOutboundProcess {
    @Autowired
    private ObMasterMapper obMasterMapper;
    @Autowired
    private ObDetailMapper obDetailMapper;
    @Autowired
    private IModuleSerialService moduleSerialService;
    @Autowired
    private StockMapper stockMapper;
    @Autowired
    private ITaskProcess taskProcess;

    @Override
    public ProcResult procWmsOutboundMasterInsert(ObMasterEntity obMaster) {
        // 对出库主单参数进行校验
        if (obMaster == null) {
            return ProcResult.error("obMaster_insert_err#001", "待写入的出库信息不能为空");
        }
        String obMasterType = obMaster.getObMasterType();
        String customerNo = obMaster.getCustomerNo();

        if (StringUtils.isBlank(obMasterType)) {
            return ProcResult.error("obMaster_insert_err#002", "出库单类型不能为空");
        }

        // 处理出库单号
        ModuleSerial moduleSerial = moduleSerialService.selectModuleSerialByCode(WmsConstants.OB_MODULE_CODE);
        if (StringUtils.isNull(moduleSerial)) {
            return ProcResult.error("obMaster_insert_err#003", "出库单序列码[OB_MASTER_NO]未在[wms_module_serial]中配置");
        }

        // 获取出库单的单号
        String obMasterNo = moduleSerialService.getSerialNo(moduleSerial);
        // 判断获取到的出库单号是否已经存在（防止重复生成）
        QueryWrapper<ObMasterEntity> obMasterNoQuery = new QueryWrapper<>();
        obMasterNoQuery.lambda().eq(ObMasterEntity::getObMasterNo, obMasterNo);
        Long count = obMasterMapper.selectCount(obMasterNoQuery);
        if (count > 0) {
            return ProcResult.error("obMaster_insert_err#004", "出库单号【" + obMasterNo + "】已存在，请重新生成");
        }
        // 写入出库单号
        obMaster.setObMasterNo(obMasterNo);
        obMasterMapper.insert(obMaster);

        return ProcResult.success("成功写入出库单,相关单号【" + obMasterNo + "】");
    }

    @Override
    public ProcResult procWmsOutboundDetailInsert(ObDetailEntity obDetail) {
        if (obDetail == null) {
            return ProcResult.error("obDetail_insert_err#001", "待写入的出库明细不能为空");
        }
        String obMasterNo = obDetail.getObMasterNo();
        if (StringUtils.isBlank(obMasterNo)) {
            return ProcResult.error("obDetail_insert_err#002", "出库单号不能为空");
        }
        // 判断对应主单是否存在？当前状态是否允许添加？
        QueryWrapper<ObMasterEntity> obMasterQuery = new QueryWrapper<>();
        obMasterQuery.lambda().eq(ObMasterEntity::getObMasterNo, obMasterNo)
                .ge(ObMasterEntity::getObMasterStatus, "1");
        Long count = obMasterMapper.selectCount(obMasterQuery);
        if (count == 0) {
            return ProcResult.error("obDetail_insert_err#003", "对应的出库单【" + obMasterNo + "】不存在或状态不允许添加");
        }
        String spuNo = obDetail.getSpuNo();
        if (StringUtils.isBlank(spuNo)) {
            return ProcResult.error("obDetail_insert_err#003", "物料编号不能为空");
        }
        BigDecimal obPlanQty = obDetail.getObPlanQty();
        // 计划出库数量不能小于0
        if (obPlanQty.compareTo(BigDecimal.ZERO) < 0) {
            return ProcResult.error("obDetail_insert_err#004", "计划出库数量不能小于【0】");
        }
        // 写入数据
        int rows = obDetailMapper.insert(obDetail);
        if (rows == 0) {
            return ProcResult.error("obDetail_insert_err#005", "写入【出库明细】失败");
        }
        return ProcResult.success("成功写入出库明细");
    }

    @Override
    @Transactional
    public ProcResult procObStockPrepareByOrderNo(String orderNo, Long creator) {
        // 工单号相关校验
        if (StringUtils.isBlank(orderNo)) {
            return ProcResult.error("ob_prepare_err#001", "工单号不能为空");
        }
        // 查询工单号是否有对应出库单存在
        QueryWrapper<ObMasterEntity> obMasterQuery = new QueryWrapper<>();
        obMasterQuery.lambda().eq(ObMasterEntity::getWorkOrderNo, orderNo).le(ObMasterEntity::getObMasterStatus, "2")
                .last("limit 1");
        ObMasterEntity obMasterEntity = obMasterMapper.selectOne(obMasterQuery);
        if (obMasterEntity == null) {
            return ProcResult.error("ob_prepare_err#002", "工单【" + orderNo + "】不存在需要【备货】的单据");
        }
        // 获取出库单号
        String obMasterNo = obMasterEntity.getObMasterNo();
        // 根据单号获取未备货完成的明细
        QueryWrapper<ObDetailEntity> obDetailQuery = new QueryWrapper<>();
        obDetailQuery.lambda().eq(ObDetailEntity::getObMasterNo, obMasterNo)
                .le(ObDetailEntity::getObDetailStatus, "2");
        List<ObDetailEntity> obDetailEntities = obDetailMapper.selectList(obDetailQuery);
        if (obDetailEntities == null || obDetailEntities.size() == 0) {
            return ProcResult.error("ob_prepare_err#003", "工单【" + orderNo + "】没有需要【备货】的明细");
        }

        // 循环处理明细，进行库存匹配
        for (ObDetailEntity obDetail : obDetailEntities) {
            // 获取明细相关信息
            Long obDetailId = obDetail.getObDetailId();
            String spuNo = obDetail.getSpuNo();
            BigDecimal planQty = obDetail.getObPlanQty();
            BigDecimal bindQty = obDetail.getObBindQty();
            // 计算出需求数量（计划数量-已备货数量）
            BigDecimal reqQty = planQty.subtract(bindQty);
            // 累计已备货数量
            BigDecimal totalBindQty = BigDecimal.ZERO;
            if (reqQty.compareTo(BigDecimal.ZERO) <= 0) {
                continue;
            }
            // 根据所需物料+需求数量匹配可用库存
            List<UsableStockInfo> usableStocks = stockMapper.selectUsableStockListBySpuNo(spuNo);
            if (usableStocks == null || usableStocks.size() == 0) {
                continue;
            }
            // 循环使用库存（暂不做拆零处理，整体库存使用）
            for (UsableStockInfo stock : usableStocks) {
                // 当前库存托盘码
                Long stockId = stock.getStockId();
                String contNo = stock.getContNo();
                String locationNo = stock.getLocationNo();
                String reelId = stock.getReelId();
                // 当前库存的可用数量
                BigDecimal remainQty = stock.getStockQty().subtract(stock.getLockedQty());
                // 锁定当前库存
                UpdateWrapper<StockEntity> updateStockUw = new UpdateWrapper<>();
                updateStockUw.lambda().eq(StockEntity::getStockId, stockId)
                        .eq(StockEntity::getVersion, stock.getVersion())
                        .set(StockEntity::getLockedQty, stock.getStockQty())
                        .set(StockEntity::getStockStatus, "1")
                        .set(StockEntity::getUpdater, creator)
                        .set(StockEntity::getUpdateDate, new Date());
                int updateRows = stockMapper.update(updateStockUw);
                if (updateRows == 0) {
                    // 库存预分配异常的处理
                    return ProcResult.error("ob_prepare_err#004", "工单【" + orderNo + "】库存预分配异常!相关库存ID【" + stockId + "】");
                }

                // 生成[wms_task]内部任务
                TaskEntity taskByStock = new TaskEntity();
                taskByStock.setTaskType(WmsTaskType.SHIPMENT_OUT.getCode());
                taskByStock.setTaskSubType(WmsTaskSubType.PREPARE_OUT.getCode());
                taskByStock.setFromContNo(contNo);
                taskByStock.setFromPosition(locationNo);
                // 去向为当前库区的出库暂存区（或者目标工位等）
                taskByStock.setToPosition("");
                taskByStock.setSpuNo(spuNo);
                taskByStock.setLotNo(stock.getLotNo());
                taskByStock.setPlanQty(remainQty);
                taskByStock.setMasterNo(obMasterNo);
                taskByStock.setDetailId(obDetailId);
                taskByStock.setStockId(stockId);
                taskByStock.setWorkOrderNo(orderNo);
                taskByStock.setCreator(creator);
                ProcResult taskInsertResult = taskProcess.procWmsTaskInsert(taskByStock);
                // 判断任务生成是否异常
                if (!WmsConstants.PROC_SUCCESS.equals(taskInsertResult.getCode())) {
                    return ProcResult.error("ob_prepare_err#005", taskInsertResult.getMessage());
                }
                // 判断当前明细配货是否完成
                totalBindQty = totalBindQty.add(remainQty);
                if (totalBindQty.compareTo(reqQty) >= 0) {
                    break;
                }
            }
            // 配货完成后更新明细信息
            obDetail.setObBindQty(bindQty.add(totalBindQty));
            obDetail.setObDetailStatus(WmsBusinessStatus.OB_DETAIL_PREPARED.getCode());
            obDetail.setComments("自动备料完成");
            obDetail.setUpdater(creator);
            obDetailMapper.updateById(obDetail);
        }
        return ProcResult.success("工单【" + orderNo + "】备料成功!");
    }

    @Override
    public ProcResult procObStockPrepare(Long obMasterId, Long creator) {
        if (StringUtils.isNull(obMasterId)) {
            return ProcResult.error("stock_prepare_err#001", "出库备货失败!备货主单ID不能为空!");
        }
        // 根据ID判断单据是否需要备货
        ObMasterEntity obMasterEntity = obMasterMapper.selectById(obMasterId);
        if (obMasterEntity == null) {
            return ProcResult.error("stock_prepare_err#002", "出库备货失败!未找到ID【" + obMasterId + "】出库主单!");
        }
        int obMasterStatus = obMasterEntity.getObMasterStatus();
        // 判断单据状态
        return null;
    }
}
